// metric data structure
// basic function :  inc/dec/snapshot

use std::{ fmt::{self}, sync::{Arc}};
use anyhow::{Result};
use dashmap::DashMap;


#[derive(Debug,Clone)]
pub struct Metrics {
    data: Arc<DashMap<String, i64>>,
}

impl Default for Metrics {
    fn default() -> Self {
        Self::new()
    }
}

impl Metrics {
    pub fn new() ->Self{
        Metrics {
            data: Arc::new(DashMap::new()),
        }
    }

    // pub fn inc(&mut self, key: &str){
    //     let counter = self.data.entry(key.to_string()).or_insert(0);
    //     *counter +=1;
    // }


    // pub fn dec(&mut self, key: &str){
    //     let counter = self.data.entry(key.to_string()).or_insert(0);
    //     *counter -=1;
    // }

    // key: impl Into<String>  其实表明是一个泛型， 任何能转为String的， 都可以是key， 不像上面   注释 的， 只限定String
    // pub fn inc(&mut self, key: impl Into<String>){
    //     let counter = self.data.entry(key.into()).or_insert(0);
    //     *counter +=1;
    // }

    // pub fn dec(&mut self, key: impl Into<String>){
    //     let counter = self.data.entry(key.into()).or_insert(0);
    //     *counter -=1;
    // }


    // 支持锁的， 内部可变， 不用mut了
    pub fn inc(&self, key: impl Into<String>) -> Result<()>{
        let mut counter = self.data.entry(key.into()).or_insert(0);
        *counter +=1;
        Ok(())
    }



    // 用了DashMap  就不用snapshot了， 它的锁都封装好了， 直接实现Display 就好

    // pub fn snapshot(&self) -> Result<HashMap<String,i64>> {
    //     //self.data.clone()
    //     Ok(self
    //         .data
    //         .read()
    //         .map_err(|e|anyhow!(e.to_string()))?
    //         .clone())
    // }

   
}


impl fmt::Display for Metrics {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
       for entry in self.data.iter() {
        writeln!(f, "{},{}", entry.key(),entry.value())?;
       }

       Ok(())
    }
}
